#include "sessionfileeventmonitor.h"
#include "fileevent.pb.h"

#include <QDBusConnection>
#include <QDBusMessage>
#include <QDBusReply>
#include <QDBusInterface>
#include <QDebug>

#include <unistd.h>

SessionFileEventMonitor::SessionFileEventMonitor(QObject *parent)
    : QObject{parent}
{
    auto userPath = QString("/org/freedesktop/Accounts/User%1").arg(getuid());
    qDebug() << "user path" << userPath;
    QDBusInterface iface("org.freedesktop.Accounts", userPath, "org.freedesktop.DBus.Properties", QDBusConnection::systemBus());
    QDBusReply<QVariant> msg = iface.call(QDBus::Block, "Get", "org.freedesktop.Accounts.User", "HomeDirectory");
    if (msg.isValid()) {
        QString homeDir = msg.value().toString();
        QString configPath = homeDir + "/.config";
        QString cachePath = homeDir + "/.cache";
        QString localPath = homeDir + "/.local";
        QString xwechatPath = homeDir + "/.xwechat";
        prefixBlackList.push_front(configPath.toStdString());
        prefixBlackList.push_front(cachePath.toStdString());
        prefixBlackList.push_front(localPath.toStdString());
        prefixBlackList.push_front(xwechatPath.toStdString());

        configPath.prepend("/data");
        cachePath.prepend("/data");
        localPath.prepend("/data");
        xwechatPath.prepend("/data");
        prefixBlackList.push_front(configPath.toStdString());
        prefixBlackList.push_front(cachePath.toStdString());
        prefixBlackList.push_front(localPath.toStdString());
        prefixBlackList.push_front(xwechatPath.toStdString());


        qDebug() << "init session monitor blacklist";
        for (auto prefix : prefixBlackList) {
            std::cout << prefix << std::endl;
        }
    } else {
        qDebug() << "init session monitor blacklist failed" << msg.error();
    }
}

void SessionFileEventMonitor::setupService()
{
    auto conn = QDBusConnection::connectToBus(QDBusConnection::SessionBus, "file event monitor");
    conn.registerService("org.ukui.SessionFileMonitor");
    conn.registerObject("/", "org.ukui.SessionFileMonitor", this, QDBusConnection::ExportAllSignals);
}

void SessionFileEventMonitor::handleFileEventProtobuf(const QByteArray &buffer)
{
    FileEvent event;
    event.ParseFromArray(buffer.constData(), buffer.size());
    // 进行权限检查，如果用户没有权限则跳过
    // fixme：从有权限到无权限也需要发送相关事件，用于更新索引
    // fixme: 文件创建时权限查询失败
//    if (!access(event.srcpath().c_str(), R_OK)) {
//        return;
//    }
//    if (event.eventtype() == 2) {
//        if (!access(event.dstpath().c_str(), R_OK)) {
//            return;
//        }
//    }

    for (auto prefix : prefixBlackList) {
        if (event.srcpath().starts_with(prefix)) {
//            qDebug() << "skip" << QString::fromStdString(event.srcpath());
            return;
        }
    }

    qDebug() << "===========recieve protobuf message===========" <<
                "pid:" << event.pid() << "command:" << QString::fromStdString(event.command()) << "type:" << event.eventtype() << "\n" <<
                "src dev:" << event.srcdev() << "src uuid:" << QString::fromStdString(event.srcuuid()) << "src id:" << event.srcino() << "src fullpath:" << QString::fromStdString(event.srcpath()) << "\n" <<
                "dst dev:" << event.dstdev() << "dst uuid:" << QString::fromStdString(event.dstuuid()) << "dst id:" << event.dstino() << "dst fullpath:" << QString::fromStdString(event.dstpath());

    emit fileEvent(event.pid(), QString::fromStdString(event.command()), event.eventtype(),
                   QString::fromStdString(event.srcuuid()), event.srcino(), QString::fromStdString(event.srcpath()),
                   QString::fromStdString(event.dstuuid()), event.dstino(), QString::fromStdString(event.dstpath()));
}
